
import {
    getFourPath,
    getCarPath,
    getLocationOutSideEdge,
    getLocationInsideEdge,
    getLocationPath,
    getCarLocationPath, 
    getArrow, 
    getTwoBesselPath, 
    getThreeBesselPath, 
    getChargingPath, 
    getChargingLightningPath,
    getContainerPath,
    getContainerNodePath
} from "@/draw/util/drawPathUtil";
import Anchor from "@/draw/item/anchor";
const interval =13;
const dashArray = [
    [0, 1],
    [0, 2],
    [1, 2],
    [0, 1, 1,2],
    [0, 2, 1,2],
    [1, 3, 1,2],
    [2, 4, 1,2],
    [3, 5, 1,2],
    [4, 6, 1,2],
    [5, 7, 1,2],
    [6, 8, 1,2],
    [7, 9, 1,2],
    [8, 10, 1,2],
]
const lineDash = [8, 10, 1,2];

const nodeDefinition = {

    afterDraw(cfg, group){
        group.anchorShapes = [];
        this._runAnimate(group, cfg.isAnimate);

        // if(cfg.clazz === 'car'){
        //     this._animate(cfg, group);
        // }
        return group;
    },


    _animate(cfg, group){
        this._onLine(cfg, group);
        // group.addShape('c');
        setTimeout(()=>{
            group.animate(()=>{
                const bbox = group.cfg.item.getBBox();
                group.cfg.item.updatePosition({x: bbox.centerX + 10, y: bbox.centerY});

            }, {duration: 500})
        }, 5000)
    },

    /**
     * 在线状态
     * @private
     */
    _onLine(cfg,group){
        const width = cfg.size[0];
        const height = cfg.size[1];
        group.addShape('circle', {
            attrs: {
                r: width/50,
                x: -width/4.25,
                y: -height/7,
                fill: '#fff'
            }
        });
        let index = 0;
        function getOnLinePath(width, height) {
            return [
                [
                    ['M', -width/3, -height/6],
                    ['Q', -width/4.25, -height/4, -width/7, -height/6],
                ],
                [
                    ['M', -width/2.7, -height/5],
                    ['Q', -width/4.25, -height/3.2, -width/9, -height/5],
                ],
                [
                    ['M', -width/2.5, -height/4.2],
                    ['Q', -width/4.25, -height/2.7, -width/13, -height/4.2],
                ]
            ]
        }
        group.addShapeGroup = [];
        setInterval(()=>{
            index = (index + 1) % 3;
            for (let i=0; i<index +1; i++){
                const path = getOnLinePath(width, height)[i];
                if(i === 0){
                    group.addShapeGroup.forEach(item => {
                        item.remove();
                    })
                    group.addShapeGroup = [];
                }
                const shape = group.addShape('path', {
                    attrs: {
                        path: path,
                        stroke: '#fff',
                        lineWidth: width/50,
                    }
                });
                group.addShapeGroup.push(shape);
            }
        }, 600)
    },


    /**
     * 动画效果
     * @param group
     * @param isAnimate
     * @private
     */
    _runAnimate(group, isAnimate){
        let index = 0;
        if(isAnimate){
            group.animate(
                ()=>{
                    const cfg = {
                        lineDash: dashArray[index].concat(lineDash)
                    }
                    index = (index + 1) % interval;
                    return cfg;
                }, {repeat: true, duration: 50}
            )
        }else{
            group.stopAnimate(true);
        }
    },

    /**
     * 设置遮罩
     * @param item
     * @param width
     * @param height
     * @param group
     * @private
     */
    _setMaskingShape(item, width, height, group, clazz){
        const addMaskingShape = item.get("addMaskingShape");
        if(!addMaskingShape){
            const addMaskingShape = group.addShape('rect', {
                attrs: {
                    width: width,
                    height: height,
                    x: clazz === 'map' ? 0 : -(width/2),
                    y: clazz === 'map' ? 0 : -(height/2),
                    radius: [4, 4],
                    lineWidth: 1,
                    stroke: '#1890ff',
                    fill: '#1890ff',
                    fillOpacity: 0.3,
                },
                name: 'masking-shape',
                draggable: true,
            });
            item.set("addMaskingShape", addMaskingShape);
        }else{
            addMaskingShape.attr({
                width: width,
                height: height ,
                x: clazz === 'map' ? 0 : -(width/2),
                y: clazz === 'map' ? 0 : -(height/2),
            })
        }
        addMaskingShape && this._setRestAnchor(group.anchorShapes, addMaskingShape);
    },

    /**
     * 设置锚点
     * @param item
     * @param group
     * @private
     */
    _setDelegateAnchors(item, group){
        const anchorShapes = group.anchorShapes;
        if(anchorShapes.length === 0){
            const maskingShape = group.get('children').find(a => a.cfg.name === 'masking-shape');
            const bbox = maskingShape ? maskingShape.getBBox() :  group.get('children')[0].getBBox();
            let points = this.getAnchorPoints(group.get('children')[0]);
            points.forEach((p, i) => {
                const anchorContainer = group.addGroup();
                new Anchor({
                    group: anchorContainer,
                    index: i,
                    model:{
                        style:{
                            x: p[0] !== 1 && p[0] !== 0 ? p[0] : bbox.minX + bbox.width * p[0],
                            y: p[1] !== 1 && p[1] !== 0 ? p[1] : bbox.minY + bbox.height * p[1]
                        }
                    }
                });
                group.anchorShapes.push(anchorContainer);
            })
        }
    },

    /**
     * 选中
     * @param name
     * @param value
     * @param item
     */
    setState(name, value, item){
        const group = item.getContainer();
        const model = item.getModel();
        if(name === 'selected' && model.size){
            const width = model.size[0];
            const height = model.size[1];
            if(value) {
                if(model.clazz !== 'line' && model.clazz !== 'quadratic'
                    && model.clazz !== 'twoBessel' && model.clazz !== 'map' && model.clazz !== 'threeBessel'){
                    this._setMaskingShape(item, width, height, group, model.clazz);
                }
                this._setDelegateAnchors(item, group);
            }else{
                const maskingShape = item.get("addMaskingShape");
                if(maskingShape){
                    maskingShape.remove();
                    item.set('addMaskingShape', null);
                }
                const anchorShapes = group.anchorShapes;
                if(anchorShapes.length > 0){
                    anchorShapes.forEach(a => a.remove());
                    group.anchorShapes = [];
                }
            }
        }
    },

    /**
     * 更新样式
     * @param cfg
     * @param node
     * @returns {*}
     */
    update(cfg, node){
        this._updateNodeStyle(cfg, node);
        return node;
    },

    /**
     * 修改node样式
     * @param cfg
     * @param node
     * @private
     */
    _updateNodeStyle(cfg, node){
      switch (cfg.clazz){
          case 'line':
              this._updateLineStyle(cfg, node);
              break;
          case 'text':
              this._updateTextStyle(cfg, node);
              break;
          case 'twoBessel':
              this._updateTwoBessel(cfg, node);
              break;
          case 'threeBessel':
              this._updateThreeBessel(cfg, node);
              break;
          case 'four':
              this._updateFour(cfg, node);
              break;
          case 'rect':
              this._updateRect(cfg, node);
              break;
          case 'car':
              this._updateCar(cfg, node);
              break;
          case  'location':
              this._updateLocation(cfg, node);
              break;
          case 'carLocation':
              this._updateCarLocation(cfg, node);
              break;
          case 'charging':
              this._updateCharging(cfg, node);
              break;
          case 'container':
              this._updateContainer(cfg, node);
              break;
          default:
              break;
      }
    },

    /**
     * 更新托盘
     * @param {*} cfg 
     * @param {*} node 
     */
    _updateContainer(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        const group = node.getContainer().getChildren();
        group.forEach(item => {
            if(item.cfg.name === 'container-edge'){
                item.attr({
                    path: getContainerPath(width, height),
                    stroke: cfg.color,
                })
            }else if(item.cfg.name === 'container-back'){
                item.attr({
                    path: getContainerNodePath(width, height),
                    fill: cfg.color,
                })
            }else if(item.cfg.name === 'conainer-text'){
                item.attr({
                    text: cfg.label
                })
            }
        })
        // node.getKeyShape().attr({
        //     path: getContainerPath(width, height),
        //     fill: cfg.color,
        //     lineWidth: 1,
        // });
    },
    /**
     * 更新充电桩
     * @param cfg
     * @param node
     * @private
     */
    _updateCharging(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        const group = node.getContainer().getChildren();
        group.forEach(item => {
            if(item.cfg.name === 'charging-shape'){
                item.attr({
                  path: getChargingPath(width, height),
                  fill: cfg.color,
                })
            }else if(item.cfg.name === 'charging-rect-shape'){
                item.attr({
                    width: width/2.5,
                    height: height/3.2,
                    x: -width/3,
                    y: -height/2.53,
                    radius: [width/18, width/18]
                })
            }else if(item.cfg.name === 'charging-lightning-shape'){
                item.attr({
                    path: getChargingLightningPath(width, height)
                })
            }
        })
    },

    /**
     * 更新停车位
     * @param cfg
     * @param node
     * @private
     */
    _updateCarLocation(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        const group = node.getContainer().getChildren();
        group.forEach(item => {
            if(item.cfg.name === 'outside-circle'){
                item.attr({
                    width: width,
                    height: height,
                    r: width/2,
                    fill:  cfg.color,
                })
            }else if(item.cfg.name === 'inside-circle'){
                item.attr({
                    width: width/2.8,
                    height: height/2.8,
                    r: width/2.8,
                    stroke: "#fff",
                    lineWidth: width/30,
                    fill: cfg.color,
                })
            }else if(item.cfg.name === 'icon'){
                item.attr({
                    path: getCarLocationPath(width, height)
                })
            }
        })
    },

    /**
     * 更新库位
     * @param cfg
     * @param node
     * @private
     */
    _updateLocation(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        const group = node.getContainer().getChildren();
        group.forEach(item => {
            if(item.cfg.name === 'outside-edge'){
                item.attr({
                    path: getLocationPath(width, height),
                    fill: cfg.backColor ? cfg.backColor : '#fff',
                    stroke: cfg.color,
                })
            }else if(item.cfg.name === 'outside-text'){
                item.attr({
                    fill: cfg.textColor ? cfg.textColor : '#000',
                })
            }
        })
    },

    /**
     * 更新车
     * @param cfg
     * @param node
     * @private
     */
    _updateCar(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        node.getKeyShape().attr({
            path: getCarPath(width, height).join(" "),
            fill: cfg.color,
            lineWidth: 1,
            rotate: Math.PI / 4,
            zIndex: 999,
        });
        // node.getKeyShape().toFront();
        if(cfg.angle){
            node.getKeyShape().rotate((cfg.angle || 0) * Math.PI / 180);
        }
    },

    /**
     * 更新矩形
     * @param cfg
     * @param node
     * @private
     */
    _updateRect(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        node.getKeyShape().attr({
            width: width,
            height: height,
            x: -width/2,
            y: -height/2,
            stroke: cfg.color,
            lineWidth: cfg.lineWidth,
            radius: [parseInt(cfg.radius), parseInt(cfg.radius)],
            fill: cfg.fillColor,
            fillOpacity: cfg.fillOpacity,
            lineDash: cfg.isDash ? [10, 10] : [0, 0]
        });
    },

    /**
     * 更新四角形状
     * @param cfg
     * @param node
     * @private
     */
    _updateFour(cfg, node){
        const width = cfg.size[0];
        const height = cfg.size[1];
        node.getKeyShape().attr({
            path: getFourPath(width, height),
            stroke: cfg.color,
            lineWidth: cfg.lineWidth
        });
    },

    /**
     * 更新三次贝塞尔曲线
     * @param cfg
     * @param node
     * @private
     */
    _updateThreeBessel(cfg, node){
        node.getKeyShape().attr({
            path: getThreeBesselPath(cfg.origin, cfg.control1, cfg.control2, cfg.target),
            stroke: cfg.color,
            lineWidth: cfg.lineWidth,
            endArrow: cfg.isArrow ? getArrow(cfg.color) : {path: []},
            lineDash: cfg.isDash ? [10, 5] : [0,0]
        });
        this._runAnimate(node.getKeyShape(), cfg.isAnimate);
    },

    /**
     * 更新二次贝尔曲线
     * @param cfg
     * @param node
     * @private
     */
    _updateTwoBessel(cfg, node){
        node.getKeyShape().attr({
            path: getTwoBesselPath(cfg.origin, cfg.control, cfg.target),
            stroke: cfg.color,
            lineWidth: cfg.lineWidth,
            endArrow: cfg.isArrow ? getArrow(cfg.color) : {path: []},
            lineDash: cfg.isDash ? [10, 5] : [0,0]
        });
        this._runAnimate(node.getKeyShape(), cfg.isAnimate);
    },

    /**
     * 修改文本样式
     * @param cfg
     * @param node
     * @private
     */
    _updateTextStyle(cfg, node){
        const groups = node.getKeyShape().getParent().getChildren();
        const textItem = groups.find(item => item.cfg.name === 'text-shape');
        // 修改文本样式
        const textStyle = textItem.attr({text: cfg.text,fontSize: cfg.fontSize,fontWeight: cfg.fontWeight, fill: cfg.color});
        const textRectShape = groups.find(item => item.cfg.name === 'text-rect-shape');
        const bbox = textStyle.getBBox();
        textRectShape.attr({width: bbox.width, x: -bbox.width/2});
        cfg.size = [bbox.width, cfg.size[1]];
    },

    /**
     * 更新锚点
     * @param groups
     * @param delegate
     * @private
     */
    _setRestAnchor(groups, delegate){
      const anchors = groups.filter(item => item.cfg.id);
      const bbox = delegate.getBBox();
      anchors.forEach(item => {
          const points = this.getAnchorPoints();
          const anchorPoint = points[item.cfg.item._cfg.index];
          item.getChildren()[0].attr({
              x: bbox.minX + bbox.width * anchorPoint[0],
              y: bbox.minY + bbox.height * anchorPoint[1]
          })
      })
    },
    /**
     * 修改线样式
     * @param cfg
     * @param node
     * @private
     */
    _updateLineStyle(cfg, node){
        node.getKeyShape().attr({
            x1: cfg.origin.x,
            y1: cfg.origin.y,
            x2: cfg.target.x,
            y2: cfg.target.y,
            stroke: cfg.color,
            lineWidth: cfg.lineWidth,
            endArrow: cfg.isArrow ? getArrow(cfg.color) : {path: []},
            lineDash: cfg.isDash ? [10, 5] : [0,0]
        })
        this._runAnimate(node.getKeyShape(), cfg.isAnimate);
    },
}

export default function (G6){
    G6.registerNode('base-node', nodeDefinition, 'single-node');
}
